﻿/*
* Copyright 2009-2010 AKABANA.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
using System;
using System.Reflection;

using Akabana.Amf.Messaging.Component;

namespace Akabana.Amf.Messaging.Service
{
    public class AbstractService
    {
        public AmfConnection amfConnection { get; set; }

        private static MethodInfo amfConnectionCallMethod = typeof(AmfConnection).GetMethod("Call", BindingFlags.Instance | BindingFlags.Public);

        protected void Call(string command, object[] args, object resultAction, object faultAction)
        {
            var resultDelegate = (Delegate)resultAction;
            var resultCallBack = new ResultCallBack(delegate(object result)
            {
                if (resultDelegate.Method.GetParameters().Length > 0)
                {
                    var resultType = result.GetType();
                    var param = resultDelegate.Method.GetParameters()[0];
                    if (resultType.IsArray  && param.ParameterType.IsArray)
                    {
                        var resultArray = (Array)result;
                        var paramArrayElementType = param.ParameterType.GetElementType();

                        var newArray = Array.CreateInstance(paramArrayElementType, resultArray.Length);

                        resultArray.CopyTo(newArray, 0);

                        resultDelegate.DynamicInvoke(newArray);
                    }
                    else
                    {
                        resultDelegate.DynamicInvoke(result);
                    }
                }
                else
                {
                    resultDelegate.DynamicInvoke();
                }
            });
            var faultDelegate = (Delegate)faultAction;
            var faultCallback = new FaultCallBack(delegate(Fault fault)
            {
                faultDelegate.DynamicInvoke(fault);
            });

            var callArgs = new object[] { command, new Responder(resultCallBack, faultCallback), args };

            amfConnectionCallMethod.Invoke(amfConnection, callArgs);
        }
    }
}
